package org.example.zpqy.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.example.zpqy.bean.AppleOne;
import org.example.zpqy.repository.AppleOneRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class AppleAiService {

    @Autowired
    private AppleOneRepository appleOneRepository;

    private final String AI_API_URL = "https://open.bigmodel.cn/api/paas/v4/chat/completions";
    private final String AI_API_KEY = "0bd7298d801d4f26b6a622aa262af4b3.AyYdND8tk1HpcLMn";

    private final String WEATHER_API_URL = "https://restapi.amap.com/v3/weather/weatherInfo";
    private final String WEATHER_API_KEY = "476fc756852a8caa003633f8074ffff5";

    private final ObjectMapper objectMapper = new ObjectMapper();

    public List<Map<String, String>> getAiAdvice(String cropName, String cityCode) {
        List<AppleOne> data = appleOneRepository.findAll();

        // 调用天气 API
        RestTemplate restTemplate = new RestTemplate();
        String weatherUrl = WEATHER_API_URL + "?city=" + cityCode + "&key=" + WEATHER_API_KEY + "&extensions=all";
        String weatherInfo = restTemplate.getForObject(weatherUrl, String.class);

        // 构建提示词
        StringBuilder sb = new StringBuilder();
        sb.append("作物：").append(cropName).append("\n\n");
        sb.append("以下是果树监测数据（氮/磷/钾/水分），请结合天气预报，逐棵分析：\n");

        // 遍历 10 棵树
        for (int i = 1; i <= 10; i++) {
            sb.append("果树编号:").append(i).append(" -> ");

            String nitrogen = getValueByAttribute(data, "氮", i);
            String phosphorus = getValueByAttribute(data, "磷", i);
            String potassium = getValueByAttribute(data, "钾", i);
            String moisture = getValueByAttribute(data, "水分", i);

            sb.append("氮=").append(nitrogen).append(", ")
                    .append("磷=").append(phosphorus).append(", ")
                    .append("钾=").append(potassium).append(", ")
                    .append("水分=").append(moisture).append("\n");
        }

        sb.append("\n天气信息：").append(weatherInfo);

        // 强制 AI 返回 JSON
        sb.append("\n\n请严格按照以下JSON数组格式输出：\n")
                .append("[\n")
                .append("  {\n")
                .append("    \"treeId\": \"果树编号\",\n")
                .append("    \"problem\": \"问题描述\",\n")
                .append("    \"risk\": \"结合实时天气以及天气预报的风险解释\",\n")
                .append("    \"advice\": \"养护建议\"\n")
                .append("  }\n")
                .append("]\n")
                .append("注意：\n")
                .append("1. 只输出JSON数组，不要输出任何其他说明文字。\n")
                .append("2. 每棵果树必须完整包含 treeId / problem / risk / advice 三段。\n")
                .append("3. 即使问题相同，也要单独完整写，不要写“与某果树相同”。\n")
                .append("4. 回答中体现出结合天气信息，如“由于明天会下雨，所以不建议浇水”。\n")
                .append("5. 只输出有问题的果树，没问题的不用输出。\n");

        // 请求体
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("model", "glm-4-flash");
        requestBody.put("messages", List.of(
                Map.of("role", "user", "content", sb.toString())
        ));

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(AI_API_KEY);

        HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);

        // 调用 AI
        ResponseEntity<Map> response = restTemplate.postForEntity(AI_API_URL, request, Map.class);

        // 解析返回结果
        List<Map<String, String>> resultList = new ArrayList<>();
        Map<String, Object> resp = response.getBody();

        if (resp != null && resp.containsKey("choices")) {
            List choices = (List) resp.get("choices");
            if (!choices.isEmpty()) {
                Map choice = (Map) choices.get(0);
                Map message = (Map) choice.get("message");
                String aiContent = message.get("content").toString().trim();

                // 第一优先：直接解析 JSON
                try {
                    JsonNode root = objectMapper.readTree(aiContent);
                    if (root.isArray()) {
                        for (JsonNode node : root) {
                            Map<String, String> item = new HashMap<>();
                            item.put("treeId", node.path("treeId").asText("未知编号"));
                            item.put("problem", node.path("problem").asText("未知问题"));
                            item.put("risk", node.path("risk").asText("暂无风险解释"));
                            item.put("advice", node.path("advice").asText("暂无养护建议"));
                            resultList.add(item);
                        }
                    }
                } catch (Exception e) {
                    // 第二优先：正则兜底解析
                    Pattern p = Pattern.compile(
                            "果树编号[:：]?(\\d+).*?问题[:：]?(.*?)风险解释[:：]?(.*?)养护建议[:：]?(.*?)(?=(果树编号|$))",
                            Pattern.DOTALL
                    );
                    Matcher m = p.matcher(aiContent);
                    while (m.find()) {
                        Map<String, String> item = new HashMap<>();
                        item.put("treeId", m.group(1).trim());
                        item.put("problem", m.group(2).trim());
                        item.put("risk", m.group(3).trim());
                        item.put("advice", m.group(4).trim());
                        resultList.add(item);
                    }
                }
            }
        }

        // 如果还是空，返回兜底提示
        if (resultList.isEmpty()) {
            Map<String, String> err = new HashMap<>();
            err.put("treeId", "0");
            err.put("problem", "未识别出问题");
            err.put("risk", "AI未能解析风险解释");
            err.put("advice", "请检查输入数据或AI返回内容");
            resultList.add(err);
        }

        return resultList;
    }

    // 工具方法：根据 attribute 找值
    private String getValueByAttribute(List<AppleOne> data, String attribute, int treeIndex) {
        for (AppleOne row : data) {
            if (row.getAttribute().contains(attribute)) {
                Integer val = row.getApptreeValue(treeIndex);
                return val == null ? "无数据" : val.toString();
            }
        }
        return "无数据";
    }
}
